package com.zhxy.util.service.store;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

import com.zhxy.util.FileTool;
import com.zhxy.util.IoTool;
import com.zhxy.util.UncaughtException;
import com.zhxy.util.api.store.FileMetadata;
import com.zhxy.util.api.store.FileStore;

/**
 * 存储在本地磁盘的FileStore实现
 * @author 刘勉
 *
 */
public class LocalDiskFileStore implements FileStore {
	
	/**
	 * 如果目录不存在，是否自动创建
	 */
	private boolean autoMakeDir = false;

	private boolean withOriginName = false;

	/**
	 * 是否每天创建一个子目录
	 */
	private boolean createPathPerDay = false;

	private String location;

	private File repositoryPath;

	/**
	 * 如果location指定的目录不存在，是否自动创建，默认是false
	 * 
	 * @param autoMakeDir
	 */
	public void setAutoMakeDir(boolean autoMakeDir) {
		this.autoMakeDir = autoMakeDir;
	}

	/**
	 * 设置后,生成的文件名包含原始文件名
	 * 
	 * @param withOriginName
	 */
	public void setWithOriginName(boolean withOriginName) {
		this.withOriginName = withOriginName;
	}

	/**
	 * 是否每天创建一个目录
	 * @param createPathPerDay
	 */
	public void setCreatePathPerDay(boolean createPathPerDay) {
		this.createPathPerDay = createPathPerDay;
	}

	/**
	 * 设置文件仓库在磁盘上的存储路径
	 * @param location
	 */
	public void setLocation(String location) {
		this.location = location;
		repositoryPath = new File(location);
	}

	public String getLocation() {
		return location;
	}

	@Override
	public String store(InputStream input, String originName) {

		FileOutputStream output = null;
		try {
			File location = generateFile(originName);

			output = new FileOutputStream(location);
			IoTool.copyStream(output, input);
			output.flush();
			output.close();

			String path = location.getPath().substring(
					repositoryPath.getPath().length() + 1);

			return path.replaceAll("\\\\", "/");
		} catch (IOException e) {
			throw new UncaughtException(e);
		} finally {
			if (output != null) {
				IoTool.close(output);
			}
		}
	}

	@Override
	public void remove(String key) {
		File file = new File(repositoryPath, key);
		file.delete();
	}

	@Override
	public FileMetadata getMetadata(String key) {
		LocalFileMetadata meta = new LocalFileMetadata();
		meta.key = key;
		return meta;
	}

	private File generateFile(String originName) {

		SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
		File path = null;

		if (createPathPerDay) {
			path = new File(repositoryPath, format.format(new Date()));
			if (autoMakeDir)
				path.mkdirs();
			else
				path.mkdir();
		} else {
			path = repositoryPath;
			if (autoMakeDir)
				path.mkdir();
		}

		String fileName = UUID.randomUUID().toString();
		if (withOriginName)
			fileName += "_" + originName;
		else
			fileName += "." + FileTool.getExtension(originName);

		return new File(path, fileName);
	}
	
	
	class LocalFileMetadata implements FileMetadata {
		
		private String key;

		@Override
		public String getKey() {
			return key;
		}

		@Override
		public String getOriginName() {
			String originName = key.split("_")[1];
			return originName;
		}

		@Override
		public Date getStoredDate() {
			File f = new File(repositoryPath, key);
			return new Date(f.lastModified());
		}

		@Override
		public long size() {
			File f = new File(repositoryPath, key);
			return f.length();
		}

		@Override
		public InputStream getInputStream() {
			File file = new File(repositoryPath, key);
			try {
				return new FileInputStream(file);
			} catch (FileNotFoundException e) {
				throw new UncaughtException(e);
			}
		}

	}
}
